package com.dlg.commons.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {

	public static Logger logger = LoggerFactory.getLogger(XssAndSqlHttpServletRequestWrapper.class);
	
	//不用转义字符
	private static final String[] avoidCharStr = {"&"};
	
	HttpServletRequest orgRequest = null; 
	
	public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {
		super(request);
		orgRequest = request;  
	}

	 /** 
     * 覆盖getParameter方法，将参数名和参数值都做xss & sql过滤。<br/> 
     * 如果需要获得原始的值，则通过super.getParameterValues(name)来获取<br/> 
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 
     */  
	@Override
    public String getParameter(String name) {  
        String value = super.getParameter(xssEncode(name));  
        if (value != null) {  
            value = xssEncode(value);  
        }  
        return value;  
    }
	
	@Override    
    public String[] getParameterValues(String name) {    
        String[] values = super.getParameterValues(name);    
        if(values != null) {    
            int length = values.length;    
            String[] escapseValues = new String[length];    
            for(int i = 0; i < length; i++){
            	escapseValues[i] = xssEncode(values[i]); 
            }    
            return escapseValues;    
        }    
        return super.getParameterValues(name);    
    }    
    
    /** 
     * 覆盖getHeader方法，将参数名和参数值都做xss & sql过滤。<br/> 
     * 如果需要获得原始的值，则通过super.getHeaders(name)来获取<br/> 
     * getHeaderNames 也可能需要覆盖 
     */
    @Override
    public String getHeader(String name) {  
        String value = super.getHeader(xssEncode(name));  
        if (value != null) {  
            value = xssEncode(value);  
        }  
        return value;  
    }  
    
    /** 
     * 获取最原始的request 
     *  
     * @return 
     */  
    public HttpServletRequest getOrgRequest() {  
        return orgRequest;  
    }  
  
    /** 
     * 获取最原始的request的静态方法 
     *  
     * @return 
     */  
    public static HttpServletRequest getOrgRequest(HttpServletRequest req) {  
        if (req instanceof XssAndSqlHttpServletRequestWrapper) {  
            return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest();  
        }  
        return req;  
    }    
    
    
    /** 
     * 将容易引起xss & sql漏洞的半角字符直接替换成全角字符 
     *  
     * @param s 
     * @return 
     */  
    private static String xssEncode(String s) {  
        if (s == null || s.isEmpty()) {  
            return s;  
        } else {  
        	boolean isVertify = sqlValidate(s);
        	if(isVertify){
        		throw new RuntimeException("输入参数包含非法字符或关键字，请检查输入参数");
        	} else {
        		s = stripXSS(s);  
        	}
        }  
        return s;
    }  
    
    /** 
     *  
     * 防止xss跨脚本攻击（替换，根据实际情况调整） 
     */  
    public static String stripXSS(String value) {  
        if (value != null) {
        	for(String avoidChar : avoidCharStr){
        		if(value.indexOf(avoidChar) == -1){
        			value = StringEscapeUtils.escapeHtml4(value);
        		}
        	}
        }  
        return value;  
    }
    
    //检查是否包含sql关键字，可以手动添加
    public static boolean sqlValidate(String str) {  
		str = str.toLowerCase();//统一转为小写    
		String badStr = "'|and|exec|execute|insert|create|drop|table|from|grant|use|group_concat|column_name|" +    
				"information_schema.columns|table_schema|union|where|select|delete|update|order|by|" +    
				"chr|mid|master|truncate|char|declare|or|--|like|//|/|%|#";    
		String[] badStrs = badStr.split("\\|");    
		for (int i = 0; i < badStrs.length; i++) {    
			if (str.equals(badStrs[i])) {
				logger.error("非法参数或关键字是："+str);
				return true;    
			}  
		}    
		return false;    
    }   
    
}
